package org.ccay.personalized.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import org.ccay.core.dispatcher.EventUtil;
import org.ccay.core.exception.ApplicationException;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.log.ILogger;
import org.ccay.core.request.IRequestContext;
import org.ccay.core.request.UserEventArgs;
import org.ccay.core.request.impl.RequestContext;
import org.ccay.core.util.CollectionUtil;
import org.ccay.core.util.JsonUtil;
import org.ccay.core.util.StringUtil;
import org.ccay.personalized.CommonSettingVO;
import org.ccay.personalized.PersonalizedSettingVO;
import org.ccay.personalized.dao.IPersonalizedSettingDao;
import org.ccay.personalized.service.IAfterSaveUserSettingHandler;
import org.ccay.personalized.service.IPersonalizedSettingService;
import org.ccay.registry.util.RegistryQueryUtil;
import org.codehaus.jackson.type.TypeReference;

/**
 * 个性化配置服务接口实现类
 * @author chaowangbang
 * @since 2012-06-15
 *
 */
@Named
//@CcayResource(code = "Setting", desc = "Ccay Setting Management")
public class PersonalizedSettingService implements IPersonalizedSettingService{
	@Inject
	private IPersonalizedSettingDao iPersonalizedSettingDao;
	
	
	private static final ILogger logger = CcayLoggerFactory.getLogger(PersonalizedSettingService.class);
	
	/**
	 * 设置个性化条数
	 */
	private static final String NUMBEROFSETTINGS = "Ccay.GlobalParamters.MaxPersonalSettings";
	
	/**
	 * 查询用户所有配置
	 * @param settingVO
	 * @return
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public List<PersonalizedSettingVO> findUserSettings(PersonalizedSettingVO settingVO) throws ApplicationException {
		// 根据传过来的userid 查询，如果有 setting_key 则加上 setting_key 条件
		return iPersonalizedSettingDao.findUserPageSetttings(settingVO);
	}

	/**
	 * 查询指定KEY指定用户的个性化配置
	 * @param settingVO 查询条件，KEY使用模糊匹配
	 * @return 个性化配置查询结果
	 * @throws ApplicationException	
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public List<PersonalizedSettingVO> findPageSettings(PersonalizedSettingVO settingVO) throws ApplicationException{
		return iPersonalizedSettingDao.findPageSetttings(settingVO);
	}

	/**
	 * 查询一条记录是否存在
	 * @param personalizedSetting
	 * @return
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public int findUserSettingNumber(PersonalizedSettingVO personalizedSetting){
		//查询根据 setting_key 联合 userId 查询
		return iPersonalizedSettingDao.findUserSettingNumber(personalizedSetting);
	}

	/**
	 * 保存页面配置，不管是更新还是保存的，限制只能保存100条
	 * 
	 * @param personalizedSettingVOList
	 * @throws ApplicationException
	 * 
	 */ 
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public void saveUserSettings(List <PersonalizedSettingVO> personalizedSettingVOList) throws ApplicationException{
		//如果没有值直接退出
		if(personalizedSettingVOList == null){
			return;
		}
		int count = 0;
		List <PersonalizedSettingVO> saveList = new ArrayList<PersonalizedSettingVO>();  //新增集合
		List <PersonalizedSettingVO> updateList = new ArrayList<PersonalizedSettingVO>();  //更新集合	 
		PersonalizedSettingVO ps = null;	 
		for(int i=0;  i<personalizedSettingVOList.size(); i++){
			 ps = personalizedSettingVOList.get(i);
			count = this.findUserSettingNumber(ps);
			if(count >0){
				updateList.add(ps);
			}else{
				saveNumberOfSettings(ps);
				saveList.add(ps);
			}
		}
		
		//执行批量更新
		if(!updateList.isEmpty()){
			iPersonalizedSettingDao.updateUserSettings(updateList);
		}
		//执行批量新增
		if(!saveList.isEmpty()){
			iPersonalizedSettingDao.createUserSettings(saveList);
			
			//查询表中记录是否大于100条，如果大于则删除过时记录
			List<PersonalizedSettingVO> userSettings = iPersonalizedSettingDao
					.findUserSettings(saveList.get(0));

			if (!CollectionUtil.isNullOrEmpty(userSettings)) {
				if (userSettings.size() > saveList.get(0).getNumberOfSettings()) {
					iPersonalizedSettingDao.deleteUserSettings(userSettings.subList(0, userSettings.size() - saveList.get(0).getNumberOfSettings()));
				}
			}
		}	
	}
	
	/**
	 * 保存单个配置，不管是更新还是保存的
	 * 先查询记录在表中是否存在，如果存在，则更新，否则就执行插入
	 * 
	 * @param personalizedSetting
	 * @throws ApplicationException
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public void saveUserSetting(PersonalizedSettingVO personalizedSetting) throws ApplicationException{
		IRequestContext context = RequestContext.getCurrent();
		if(context.getUser()!=null){
			personalizedSetting.setUserId(context.getUser().getUserId());
			int count = this.findUserSettingNumber(personalizedSetting);
			//判断count是否大于等于1,如果大于等于1就执行更新一条记录，否则执行插入一条记录
			if(count >= 1){
				iPersonalizedSettingDao.updateUserSetting(personalizedSetting);
			}else{
				saveNumberOfSettings(personalizedSetting);
				iPersonalizedSettingDao.createUserSetting(personalizedSetting);

				//查询表中记录是否大于100条，如果大于则删除过时记录
				List<PersonalizedSettingVO> userSettings = iPersonalizedSettingDao
						.findUserSettings(personalizedSetting);

				if (!CollectionUtil.isNullOrEmpty(userSettings)) {
					if (userSettings.size() > personalizedSetting.getNumberOfSettings()) {
						iPersonalizedSettingDao.deleteUserSettings(userSettings.subList(0, userSettings.size() - personalizedSetting.getNumberOfSettings()));
					}
				}
			}
		}
		// 更新session中的global个性化 add by linshijian @2013-9-4
		if(personalizedSetting.getSettingKey().equals("global")){
			try {
				Map contentMap = JsonUtil.stringToObject(personalizedSetting.getSettingContent(), Map.class);
				String themeName = (String) findCurrentUserGlobalSettings("theme", "", contentMap);
				String timeZone = (String) findCurrentUserGlobalSettings("timeZone", "076+8", contentMap);
				if(timeZone != null && timeZone.length() > 4){
					timeZone = timeZone.substring(3);
				}
				UserEventArgs args = new UserEventArgs();
				// "随系统默认时，此时设置session为系统默认"
				if(StringUtil.isNullOrEmpty(themeName)){
					themeName = RegistryQueryUtil.getValue("Ccay.GlobalParamters.DefaultTheme");
				}
				args.put("theme", themeName);
				args.put("timeZone", timeZone);
				// 执行保存个性化后的事件
				EventUtil.dispatch(IAfterSaveUserSettingHandler.class, this, args);
			} catch (IOException e) {
				logger.debug("update the user global settings in session error. and the last theme is effect.",e);
			}
		}
	}
	
	/**
	 * 删除指定配置
	 * @param settingId
	 * @param userId
	 * @throws ApplicationException
	 * 判断 setting_key != "global"， global为全局变量，不能删除
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public void deleteUserSetting(int settingId) throws ApplicationException{
		//删除都通过 settingId 与 userid 来做
		PersonalizedSettingVO pls = new PersonalizedSettingVO(settingId,0);
		iPersonalizedSettingDao.deleteUserSetting(pls);
	}
	
	/**
	 * 删除指定多个配置
	 * @param personalizedSettingVOList
	 * @throws ApplicationException
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public void deleteUserSettings(List <PersonalizedSettingVO> personalizedSettingVOList) throws ApplicationException{
		//删除都通过 settingId 与 userid 来做
		iPersonalizedSettingDao.deleteUserSettings(personalizedSettingVOList);
	}
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public CommonSettingVO findPushMessageSettings()
			throws ApplicationException {
		String parentPath = "App.PushMessage";
		//例外定制
		Map<String,String> exclude = new HashMap<String,String>();
		exclude.put("Global", "Global");
		exclude.put("SpecifyRole", "SpecifyRole");
		boolean allDisabled = false;	
		CommonSettingVO  pushMessage = new CommonSettingVO();
		pushMessage.setName("App.PushMessage");
		pushMessage.setDisplayName("PushMessage");
		//如果返回的 设置不是1 那么禁用html效果
		if(!RegistryQueryUtil.getBooleanValue("Ccay.GlobalParamters.EnablePushMessage")){
			pushMessage.setEnabled(false);
			allDisabled = true;
		}
		
		/**
		 * 获取数据字典配置的消息
		 */
		if(RegistryQueryUtil.hasRegistryItem("App.PushMessage")){
			//[{"name":"name","displayName":"displayName","value":"value","enabled":"true/false"},...]
			String jsonValue = RegistryQueryUtil.getValue("App.PushMessage");
			TypeReference<List<CommonSettingVO>> type = new TypeReference<List<CommonSettingVO>>(){};
			List<CommonSettingVO> vos = new ArrayList<CommonSettingVO>();
			try {
				vos = JsonUtil.stringToObject(jsonValue,type);
			} catch (Exception e) {
				logger.warn("can not convert String {0} to CommonSettingVO!");
			}
			for(CommonSettingVO vo : vos){
				//如果是例外 那么不查询出来
				if(exclude.containsKey(vo.getName())){
					continue;
				}
				if(allDisabled){
					vo.setEnabled(false);
				} else if(RegistryQueryUtil.hasRegistryItem("App.PushMessage."+vo.getName()+".Enabled")
						&& RegistryQueryUtil.getBooleanValue("App.PushMessage."+vo.getName()+".Enabled")){
					vo.setEnabled(true);
				}
				pushMessage.getDatas().add(vo);
			}
		}
		//排序
		pushMessage.compareDatas("asc", "flag");
		return pushMessage;
		
	}
	
	/* (non-Javadoc)
	 * @see org.ccay.personalized.service.IPersonalizedSettingService#findCurrentUserSettings()
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public List<PersonalizedSettingVO> findCurrentUserSettings() throws ApplicationException {
		PersonalizedSettingVO settingVO = new PersonalizedSettingVO();
		IRequestContext context = RequestContext.getCurrent();
		settingVO.setUserId(context.getUser().getUserId());
		return iPersonalizedSettingDao.findUserPageSetttings(settingVO);
	}
	
	
	/* (non-Javadoc)
	 * @see org.ccay.personalized.service.IPersonalizedSettingService#findCurrentUserGlobalSettings()
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public Map<String,Object> findCurrentUserGlobalSettings() throws ApplicationException {
		IRequestContext context = RequestContext.getCurrent();
		PersonalizedSettingVO settingVO = new PersonalizedSettingVO();
		settingVO.setUserId(context.getUser().getUserId());
		settingVO.setSettingKey("global");
		// 用户的global设置
		List<PersonalizedSettingVO> globalList = iPersonalizedSettingDao.findUserPageSetttings(settingVO);
		if(globalList.isEmpty()){
			return null;
		}
		PersonalizedSettingVO globalSettings = globalList.get(0);
		// 若个性化为空，返回null，否则取个性化数据，并转换为map
		if(globalSettings != null){
			String globalSettingsContent = globalSettings.getSettingContent();
			try {
				return (Map<String, Object>) JsonUtil.stringToObject(globalSettingsContent, Map.class);
			} catch (IOException e) {
				logger.error("transform user global settings(String) to Map error.", e);
			}
		}
		return null;
	}
	
	/* (non-Javadoc)
	 * @see org.ccay.personalized.service.IPersonalizedSettingService#findCurrentUserGlobalSettings(java.lang.String, java.lang.String)
	 */
//	@CcayOperation(policy=SecurityPolicy.AllLogonUser)
	public Object findCurrentUserGlobalSettings(String key, String defaultValue, Map<String, Object> globalSetting) {
		try {
			// 获得用户全局个性化
			if(globalSetting == null){
				globalSetting = findCurrentUserGlobalSettings();
			}
			// 为空时返回默认值
			if(globalSetting == null){
				return defaultValue;
			}
			// globalSetting中的common
			Map<String, Object> common = (Map<String, Object>) globalSetting.get("common");
			
			if(common == null){
				logger.debug("Get the value from common settings is null and set it to default value : {0}" + defaultValue);
				return defaultValue;
			}
			// 获得common中的对应的key的值
			Object value = common.get(key);
			// 查询出来的值若为空 返回默认值
			if(value == null){
				return defaultValue;
			}
			// 返回个性化的值
			return value;
		} catch (ApplicationException e) {
			// 异常是返回指定的默认值
			logger.error("find user's global setting error.", e);
			return defaultValue;
		}
		
	}
	
	/**
	 * 保存页面配置，默认保存保存100条，否则保存numberOfSettings条
	 * @param personalizedSetting
	 * @return
	 * @throws ApplicationException
	 */
	private void saveNumberOfSettings(PersonalizedSettingVO personalizedSetting)throws ApplicationException{
		personalizedSetting.setNumberOfSettings(RegistryQueryUtil.getIntegerValue(NUMBEROFSETTINGS));
	}
	
}